package com.siwei.mes.sync.erp.service;

import com.siwei.mes.common.util.JsonUtils;
import com.siwei.mes.entity.UploadLaboratoryEntity;
import com.siwei.mes.entity.erp.Itemorder;
import com.siwei.mes.entity.erp.Rwdextra;
import com.siwei.mes.entity.experiment.Experiment;
import com.siwei.mes.entity.experiment.ExperimentDetail;
import com.siwei.mes.entity.experiment.ItemorderExtend;
import com.siwei.mes.entity.materials.Materials;
import com.siwei.mes.entity.mixproportion.MixProportion;
import com.siwei.mes.entity.sync.erp.ErpProject;
import com.siwei.mes.entity.system.TestProjectInfo;
import com.siwei.mes.enums.MaterialsEnum;
import com.siwei.mes.enums.SystemParamEnum;
import com.siwei.mes.enums.TestProjectTypeEnum;
import com.siwei.mes.mapper.ItemorderExtendMapper;
import com.siwei.mes.mapper.experiment.ExperimentDetailMapper;
import com.siwei.mes.mapper.experiment.ExperimentItemorderMapper;
import com.siwei.mes.mapper.experiment.ExperimentMapper;
import com.siwei.mes.mapper.mixProportion.MixProportionMapper;
import com.siwei.mes.mapper.syncErp.ErpProjectMapper;
import com.siwei.mes.mapper.system.TestProjectInfoMapper;
import com.siwei.mes.service.erp.ItemorderService;
import com.siwei.mes.service.erp.RwdextraIronMarkService;
import com.siwei.mes.service.erp.RwdextraService;
import com.siwei.mes.service.experiment.ExperimentService;
import com.siwei.mes.service.materials.MaterialsService;
import com.siwei.mes.service.system.SystemParamService;
import com.siwei.mes.sync.config.SyncProcessorService;
import com.siwei.mes.sync.erp.entity.GenConcreteResult;
import com.siwei.mes.sync.erp.entity.ItemorderFinish;
import com.siwei.mes.sync.erp.service.impl.*;
import com.siwei.mes.upload.erp.UploadErpService;
import com.siwei.mes.upload.erp.entity.ErpAddTaskPhbLog;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.siwei.mes.common.exception.handler.MessageHandler.assertTrue;

/**
 * 生产混凝土试验
 *
 * @Description: 生产混凝土试验
 * @Version: 1.0
 * @author: mlchen
 * @date: 2024/8/8 21:43
 */
@Service
public class GenConcreteService extends GenAbstractService {
    private static final Logger log = LoggerFactory.getLogger("erp");
    @Resource
    private RwdextraService rwdextraService;
    @Resource
    private ItemorderService itemorderService;
    @Resource
    private TestProjectInfoMapper testProjectInfoMapper;
    @Resource
    private ExperimentItemorderMapper experimentItemorderMapper;
    @Resource
    private SystemParamService systemParamService;
    @Resource
    private ItemorderExtendMapper itemorderExtendMapper;
    @Resource
    private SyncProcessorService syncProcessorService;
    @Resource
    private GenKsExperimentService genKsExperimentService;
    @Resource
    private GenKllzExperimentService genKllzExperimentService;
    @Resource
    private GenKzExperimentService genKzExperimentService;
    @Resource
    private GenBatchExperimentService genBatchExperimentService;
    @Resource
    private GenQuickExperimentService genQuickExperimentService;
    @Resource
    private GenXnbgExperimentService genXnbgExperimentService;
    @Resource
    private GenKllzTieBiaoExperimentService genKllzTieBiaoExperimentService;
    @Resource
    private ExperimentMapper experimentMapper;
    @Resource
    private RwdextraIronMarkService rwdextraIronMarkService;
    @Resource
    private ErpProjectMapper erpProjectMapper;
    @Resource
    private ExperimentService experimentService;
    @Resource
    private MixProportionMapper mixProportionMapper;
    @Resource
    private MaterialsService materialsService;
    @Resource
    private UploadErpService uploadErpService;
    @Resource
    private ExperimentDetailMapper experimentDetailMapper;

    /**
     * 获取所有混凝土的试验项目  key:试验项目code   value:试验项目对象
     *
     * @return
     */
    private Map<String, TestProjectInfo> getTestProjectInfoMap() {
        List<TestProjectInfo> list = testProjectInfoMapper.getList(new TestProjectInfo().setTestType(TestProjectTypeEnum.CONCRETE.getCode()));
        return list.stream().collect(Collectors.toMap(TestProjectInfo::getTestCode, obj -> obj));
    }

    /**
     * 未生成配合比编号
     *
     * @return
     */
    public List<String> notGenPhbNoList() {
        List<String> notGenPhbNoList = new ArrayList<>();
        notGenPhbNoList.add("1");
        notGenPhbNoList.add("2");
        notGenPhbNoList.add("3");
        return notGenPhbNoList;
    }

    /**
     * 生成对应的混凝土试验台账
     *
     * @param itemorderFinish 小票完成对象
     * @return
     */
    public GenConcreteResult createConcreteExperiment(ItemorderFinish itemorderFinish) {
        log.info("开始生成对应的混凝土试验台账");
        Integer frwdh = itemorderFinish.getFRwdh();
        Integer itemorderId = itemorderFinish.getITID();
        String fromItemoderNo = itemorderFinish.getFromItemoderNo();
        GenConcreteResult genConcreteResult = new GenConcreteResult();
        genConcreteResult.setIsSuccess(true);
        genConcreteResult.setIsExecFlag(true);


        Rwdextra rwdextra = rwdextraService.selectByFrwdh(frwdh);
        if (rwdextra == null) {
            log.info("ERP任务单信息不存在,不生成混凝土试验台账，任务单：【{}】", frwdh);
            return genConcreteResult;
        }

        /**这里查询小票信息 并且插入对应小票的扩展记录表*/
        Itemorder itemorder = itemorderService.loadByItIdAndCreateFromItemoderNo(itemorderId, fromItemoderNo);
        if (itemorder == null) {
            log.info("ERP小票信息不存在，不生成混凝土试验台账，小票id：【{}】", itemorderId);
            return genConcreteResult;
        }

        List<String> notGenPhbNoList = this.notGenPhbNoList();

        /**配合比编号*/
        String phbNo = rwdextra.getPhbshow();
        log.info("取配合比编号phbshow：【{}】", phbNo);
        if (StringUtils.isBlank(phbNo)) {
            phbNo = rwdextra.getRwdextraInfo() != null ? rwdextra.getRwdextraInfo().getFPhbNo() : null;
        }
        /**工程名称*/
        String gcmc = rwdextra.getRwdextraInfo() != null ? rwdextra.getRwdextraInfo().getFGcmc() : null;
        /**是否是铁标工程*/
        boolean isIronMark = false;
        ErpProject erpProject = erpProjectMapper.selectByName(gcmc);
        if (erpProject != null && erpProject.getIsIronMark() == 1) {
            isIronMark = true;
        }
        log.info("生成对应的混凝土试验台账，判断工程：【{}】是否是铁标工程：【{}】,对应配合比：【{}】", gcmc, isIronMark, phbNo);
        /**这里判断是否需要插入到铁标中间表去记录一下*/
        if (StringUtils.isBlank(phbNo) && isIronMark) {
            log.info("该任务单配合比编号为空，不参与自动生成混凝土试验台账，任务单：【{}】", frwdh);
            /**判断对应物料是否绑定配合比  如果绑定了就不需要添加到关联表*/
            Materials materials = materialsService.checkIsExist(MaterialsEnum.CONCRETE.getCode(), MaterialsEnum.CONCRETE.getName(), itemorder.getTpz());
            if (materials != null && StringUtils.isNotBlank(materials.getPhbNo())) {
                log.info("该任务单物料【{}】绑定了配合比【{}】，直接推送给ERP，任务单：【{}】", itemorder.getTpz(), materials.getPhbNo(), frwdh);

                MixProportion selectByPhbNo = mixProportionMapper.selectByPhbNo(materials.getPhbNo());
                if (selectByPhbNo != null) {
                    /**推送到erp*/
                    try {
                        ErpAddTaskPhbLog erpAddTaskPhbLog = new ErpAddTaskPhbLog();
                        erpAddTaskPhbLog.setTaskIds(frwdh.toString());
                        erpAddTaskPhbLog.setPhbId(Integer.valueOf(selectByPhbNo.getErpPhbId()));
                        erpAddTaskPhbLog.setPhbNo(materials.getPhbNo());
                        uploadErpService.uploadAddTaskPhbLog(erpAddTaskPhbLog, false);
                    } catch (Exception e) {
                        log.info("组装推送到erp失败，失败原因：{}", e.getMessage());
                    }
                }
            } else {
                /**新增铁标需求关联表*/
                rwdextraIronMarkService.addInfo(frwdh, gcmc, itemorder.getTpz());
                return genConcreteResult;
            }
        }

        genConcreteResult.setRwdextra(rwdextra);
        genConcreteResult.setItemorder(itemorder);
        Float scquantity = itemorder.getScquantity() == null ? 0 : itemorder.getScquantity();
        genConcreteResult.setScQuantity(scquantity);

        if (notGenPhbNoList.contains(phbNo)) {
            log.info("该任务单配合比编号为【{}】，不参与自动生成混凝土试验台账，任务单：【{}】", JsonUtils.getJson(notGenPhbNoList), frwdh);
            /**新增铁标需求关联表*/
            rwdextraIronMarkService.addInfo(frwdh, gcmc, itemorder.getTpz());
            return genConcreteResult;
        }


        if (scquantity == 0) {
            log.info("该小票的生产方量不满足条件，不生成混凝土试验委托，任务单：【{}】，小票id：【{}】，生产方量：【{}】", frwdh, itemorderId, scquantity);

            /**判断是否处理转料小票逻辑开关*/
            String systemParamValue = systemParamService.selectBySystemCode(SystemParamEnum.GEN_FROM_ITEMORDER, "0");
            if (StringUtils.isBlank(systemParamValue) || "0".equals(systemParamValue)) {
                /**没有开启装料小票逻辑开关 直接跳过*/
                log.info("没有开启转料小票逻辑开关 直接跳过！");
                return genConcreteResult;
            }
            log.info("判断是否有转料小票逻辑");
            float fhquantity = itemorder.getFhquantity() == null ? 0 : itemorder.getFhquantity();
            if (fhquantity > 0 && StringUtils.isNotBlank(fromItemoderNo)) {
                log.info("小票生产方量等于0并且发货方量为：【{}】,有转料来源小票号：【{}】", fhquantity, fromItemoderNo);
                /**处理转料小票逻辑*/
                Float formItemorderNumber = this.genFormItemorderInfo(itemorder, fromItemoderNo);
                log.info("处理小票转料逻辑完毕，对应小票号：【{}】，数量：【{}】", itemorder.getItemorderno(), itemorder.getScquantity());

                if (formItemorderNumber == 0) {
                    log.info("小票生产方量为0，不执行生成试验委托逻辑，没有意义");
                    return genConcreteResult;
                }
            }

            if (StringUtils.isBlank(fromItemoderNo) && scquantity == 0) {
                log.info("小票生产方量为0，不执行生成试验委托逻辑，没有意义");
                return genConcreteResult;
            }
        }


        /**所有的试验台账id*/
        List<String> experimentIdList = new ArrayList<>();

        /**获取所有混凝土相关的试验项目*/
        Map<String, TestProjectInfo> testProjectInfoMap = this.getTestProjectInfoMap();
        /**生成混凝土快检*/
        Long quickExperimentId = genQuickExperimentService.genExperiment(rwdextra, itemorder, testProjectInfoMap);
        this.addExperimentIdList(experimentIdList, quickExperimentId);
        /**生成混凝土抗压强度*/
        Long kyqdExperimentId = genBatchExperimentService.genExperiment(rwdextra, itemorder, testProjectInfoMap);
        this.addExperimentIdList(experimentIdList, kyqdExperimentId);
        /**生成抗渗强度*/
        Long ksExperimentId = genKsExperimentService.genExperiment(rwdextra, itemorder, testProjectInfoMap);
        this.addExperimentIdList(experimentIdList, ksExperimentId);
        /**生成抗折强度*/
        Long kzExperimentId = genKzExperimentService.genExperiment(rwdextra, itemorder, testProjectInfoMap);
        this.addExperimentIdList(experimentIdList, kzExperimentId);
        /**生成混凝土综合性能报告*/
        Long xnbgExperimentId = genXnbgExperimentService.genExperiment(rwdextra, itemorder, testProjectInfoMap);
        this.addExperimentIdList(experimentIdList, xnbgExperimentId);

        Long kllzExperimentId = null;
        if (isIronMark) {
            /**生成抗氯离子*/
            kllzExperimentId = genKllzTieBiaoExperimentService.genExperiment(rwdextra, itemorder, testProjectInfoMap);
            this.addExperimentIdList(experimentIdList, kllzExperimentId);
        } else {
            /**生成抗氯离子*/
            kllzExperimentId = genKllzExperimentService.genExperiment(rwdextra, itemorder, testProjectInfoMap);
            this.addExperimentIdList(experimentIdList, kllzExperimentId);
        }
        genConcreteResult.setExperimentIdList(experimentIdList);
        if (kyqdExperimentId != null) {
            genConcreteResult.setKyExperimentId(String.valueOf(kyqdExperimentId));
        }
        if (ksExperimentId != null) {
            genConcreteResult.setKsExperimentId(String.valueOf(ksExperimentId));
        }
        if (kzExperimentId != null) {
            genConcreteResult.setKzExperimentId(String.valueOf(kzExperimentId));
        }
        if (kllzExperimentId != null) {
            genConcreteResult.setKllExperimentId(String.valueOf(kllzExperimentId));
        }

        log.info("开始处理推送数据到协会。。。。");
        /**判断是否开启推送推送混凝土试验台账到协会开关*/
        String systemParamValue = systemParamService.selectBySystemCode(SystemParamEnum.PUSH_CONCRETE_EXPERIMENT_TO_XH, "0");
        if (StringUtils.isBlank(systemParamValue) || "0".equals(systemParamValue)) {
            log.info("系统参数：【{}】自动生成混凝土试验委托，暂未开启推送混凝土试验台账到协会，不推送！", SystemParamEnum.PUSH_CONCRETE_EXPERIMENT_TO_XH);
            return genConcreteResult;
        }
        if (!experimentIdList.isEmpty()) {
            log.info("自动生成混凝土试验委托，推送数据到协会中，试验台账集合：【{}】", experimentIdList);

            /**这里有多个拆分成一个一个的推送  防止数据并发重复 反正都是队列一个一个处理一样的*/
            for (String experimentId : experimentIdList) {
                List<Experiment> hntExperiment = new ArrayList<>();
                /**判断是否推送抗压强度*/
                if (kyqdExperimentId != null && experimentId.equals(String.valueOf(kyqdExperimentId))) {
                    String kyValue = systemParamService.selectBySystemCode(SystemParamEnum.PUSH_CONCRETE_EXPERIMENT_TO_KY, "0");
                    if (kyValue == null || "0".equals(kyValue)) {
                        log.info("系统参数：【{}】自动生成混凝土抗压强度试验委托，暂未开启推送混凝土抗压强度试验台账到协会，不推送！", SystemParamEnum.PUSH_CONCRETE_EXPERIMENT_TO_KY);
                        continue;
                    }
                    hntExperiment = experimentMapper.getHntKyExperiment();

                }
                /**判断是否推送抗渗等级委托*/
                if (ksExperimentId != null && experimentId.equals(String.valueOf(ksExperimentId))) {
                    String ksValue = systemParamService.selectBySystemCode(SystemParamEnum.PUSH_CONCRETE_EXPERIMENT_TO_KS, "0");
                    if (ksValue == null || "0".equals(ksValue)) {
                        log.info("系统参数：【{}】自动生成混凝土抗渗试验委托，暂未开启推送混凝土抗渗试验台账到协会，不推送！", SystemParamEnum.PUSH_CONCRETE_EXPERIMENT_TO_KS);
                        continue;
                    }
                    hntExperiment = experimentMapper.getHntKsExperiment();
                }
                /**判断是否推送抗折强度*/
                if (kzExperimentId != null && experimentId.equals(String.valueOf(kzExperimentId))) {
                    String kzValue = systemParamService.selectBySystemCode(SystemParamEnum.PUSH_CONCRETE_EXPERIMENT_TO_KZ, "0");
                    if (kzValue == null || "0".equals(kzValue)) {
                        log.info("系统参数：【{}】自动生成混凝土抗折试验委托，暂未开启推送混凝土抗折试验台账到协会，不推送！", SystemParamEnum.PUSH_CONCRETE_EXPERIMENT_TO_KZ);
                        continue;
                    }
                }

                Experiment experiment = experimentService.loadById(Long.parseLong(experimentId));

                if (experiment == null) {
                    log.error("未查询到品控对应的台账信息！试验委托主键id :" + experimentId);
                    continue;
                }
                if (!MaterialsEnum.CONCRETE.getCode().equals(experiment.getExperimentType())) {
                    continue;
                }
                if (StringUtils.isBlank(experiment.getPhb())) {
                    log.error("配合比不存在，上传失败！不允许上传至协会！台账编号 :" + experiment.getExperimentNo());
                    continue;
                }
                if (experiment.getMoldingTime() == null) {
                    log.error("成型日期异常，上传失败！台账编号 :" + experiment.getExperimentNo());
                    continue;
                }

                List<ExperimentDetail> list = experimentDetailMapper.getList(new ExperimentDetail().setExperimentId(experiment.getId()));
/*                //龄期
                String lq = "";

                for (ExperimentDetail detail : list) {
                    //混凝土抗压
                    if (detail.getTestProjectCode().equals(TestProjectEnum.CONCRETE_PARAM_KYQD.getCode())) {
                        ConcreteKyqd concreteKyqd = detail.getObjJson().toJavaObject(ConcreteKyqd.class);
                        if (concreteKyqd != null && StringUtils.isNotBlank(concreteKyqd.getLq())) {
                            lq = concreteKyqd.getLq();
                        } else if (detail.getTestProjectCode().equals(TestProjectEnum.CONCRETE_PARAM_KSDJ.getCode())) {
                            ConcreteKsdj concreteKsdj = detail.getObjJson().toJavaObject(ConcreteKsdj.class);
                            if (concreteKsdj != null && StringUtils.isNotBlank(concreteKsdj.getLq())) {
                                lq = concreteKsdj.getLq();
                            }
                        } else if (detail.getTestProjectCode().equals(TestProjectEnum.CONCRETE_PARAM_KZQD.getCode())) {
                            ConcreteKzqd concreteKzqd = detail.getObjJson().toJavaObject(ConcreteKzqd.class);
                            if (concreteKzqd != null && StringUtils.isNotBlank(concreteKzqd.getLq())) {
                                lq = concreteKzqd.getLq();
                            }
                        }
                    }
                }*/

                /**根据配合比编号查询对应的龄期*/
                MixProportion mixProportion = mixProportionMapper.selectByPhbNo(experiment.getPhb());
                assertTrue(mixProportion == null, "配合比不存在，上传失败！不允许上传至协会！台账编号 :" + experiment.getExperimentNo());

                String proportionLq = mixProportion.getProportionLq();
                log.info("上传协会数据，根据配合比查询到的龄期：【{}】", proportionLq);

                if (StringUtils.isBlank(proportionLq)) {
                    log.error("配合比龄期为空，上传失败！不允许上传至协会！台账编号 :" + experiment.getExperimentNo());
                    continue;
                }
                syncProcessorService.submitRequest(new UploadLaboratoryEntity().setExperimentId(Collections.singletonList(experimentId)).setUploadState(1).setHntExperiment(hntExperiment));
            }
        }
        return genConcreteResult;
    }

    /**
     * 处理小票转料逻辑
     *
     * @param itemorder      现有小票
     * @param fromItemoderNo 转料小票号
     * @return
     */
    private Float genFormItemorderInfo(Itemorder itemorder, String fromItemoderNo) {
        log.info("开始处理小票转料逻辑，现有小票：【{}】，转料小票号：【{}】", itemorder.getItemorderno(), fromItemoderNo);
        /**查询转料小票信息*/
        Itemorder fromItemorderInfo = itemorderService.loadByItemorderNo(fromItemoderNo);
        if (fromItemorderInfo == null) {
            log.info("查询转料信息不存在，不处理。直接跳过！转料小票号：【{}】", fromItemorderInfo);
            return (float) 0;
        }

        /**查询转料小票绑定的所有试验委托*/
        List<Long> experimentIdList = experimentItemorderMapper.selectByItemorderId(fromItemorderInfo.getItid());
        if (experimentIdList.isEmpty()) {
            log.info("该转料小票号，暂无一条试验委托，不处理。直接跳过！转料小票号：【{}】", fromItemoderNo);
            return (float) 0;
        }
        ItemorderExtend nowExtend = itemorder.getItemorderExtend();//现有小票扩展信息
        ItemorderExtend fromExtend = fromItemorderInfo.getItemorderExtend();//转料小票扩展信息

        float fromBehalfNumber = fromExtend.getBehalfNumber() == null ? 0 : fromExtend.getBehalfNumber();//转料小票代表数量
        float nowBehalfNumber = nowExtend.getBehalfNumber() == null ? 0 : nowExtend.getBehalfNumber();//现有小票代表数量

        log.info("处理小票代表数量，转料小票代表数量：【{}】，现有小票代表数量：【{}】", fromBehalfNumber, nowBehalfNumber);
        /**处理转料小票的扩展信息代表数量
         * 转料小票代表数量=转料小票数量-现有小票代表数量
         */
        fromExtend.setBehalfNumber(fromBehalfNumber - nowBehalfNumber);
        fromExtend.setUpdateTime(new Date());
        itemorderExtendMapper.updateByPrimaryKeySelective(fromExtend);

        log.info("修改转料小票：【{}】，数量：【{}】", fromItemoderNo, fromExtend.getBehalfNumber());
        /**这里最终返回装料小票的方量出去*/
        return fromExtend.getBehalfNumber();
    }

    /**
     * 添加到集合中
     *
     * @param experimentIdList
     * @param experimentId
     */
    public void addExperimentIdList(List<String> experimentIdList, Long experimentId) {
        if (experimentId == null) {
            return;
        }
        String id = String.valueOf(experimentId);
        if (!experimentIdList.contains(id)) {
            experimentIdList.add(id);
        }
    }
}
